package com.pz.operation01;

import com.pz.operation01.pojo.LetterInfo;
import com.pz.operation01.pojo.WordsInfo;
import com.pz.util.FileUtil;
import com.pz.util.MapSortUtil;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.xmlbeans.impl.xb.xsdschema.ListDocument;
import sun.rmi.runtime.Log;

import static java.util.Map.Entry.comparingByValue;
import static java.util.stream.Collectors.toMap;

import java.io.IOException;
import java.text.DecimalFormat;
import java.time.Year;
import java.util.*;

public class WordAnalyse {
    /**
     *  输出某个英文文本文件中 26 字母出现的频率，由高到低排列，并显示字母出现的百分比，精确到小数点后面两位。
     * @param path   文件路径
     * */
    public static void showRate(String path) throws IOException {
        Long num = Long.valueOf(0);  //26个字符出现的总数
        FileUtil fileUtil = new FileUtil(path);

        Map<String, LetterInfo> letters = null;
        {
            letters = new HashedMap<String,LetterInfo>();  //创建26字母暂存表
            for (char i = 'a'; i <= 'z'; i++){
                letters.put(String.valueOf(i),new LetterInfo(String.valueOf(i),0,0.00));
            }
        }
        char[] tempLetters;
        tempLetters = fileUtil.readFile().toCharArray(); //暂存文件字符内容

        for(int i = 0; i < tempLetters.length-2; i++){
            char temp = tempLetters[i];
            if((temp>='a'&&temp<='z') || (temp>='A'&&temp<='Z')){
                if(temp>='A'&&temp<='Z'){
                    temp+=32; //转为小写
                }
                LetterInfo info = letters.get(String.valueOf(temp));
                info.setNum(info.getNum()+1);
                letters.put(String.valueOf(temp),info);
                num++;
            }
        }
        System.out.println("字符总数："+(tempLetters.length-2));
        System.out.println("26字母总数："+num);

        for (char i = 'a'; i <= 'z'; i++){
            DecimalFormat df = new DecimalFormat("#.0000");
            LetterInfo info = letters.get(String.valueOf(i));
            Double d = Double.valueOf(info.getNum())/Double.valueOf(num);
            info.setRate(Double.valueOf(df.format(d)));
        }
        System.out.println("======");
        sortByRate(letters);
    }
    public static void showLetters(Map<String, LetterInfo> letters){
        for (char i = 'a'; i <= 'z'; i++){
            System.out.println(i+"-->"+letters.get(String.valueOf(i)).toString());
        }
    }
    //按照字母频率降序排列
    public static void sortByRate(Map<String, LetterInfo> letters){
        List<LetterInfo> list = new ArrayList<>();
        for (char i = 'a'; i <= 'z'; i++){
            list.add(letters.get(String.valueOf(i)));
        }
        list.sort(Comparator.comparing(LetterInfo::getRate).reversed());
        for (LetterInfo temp : list){
            System.out.println(temp);
        }
    }


    /**
     *  输出文件中所有不重复的单词，按照出现次数由多到少排列，出现次数同样多的，以字典序排列
     *  不支持缩写 --> I'm
     *  返回该单词组
     * */
    public static List<WordsInfo> DistinctWords(String path) throws IOException{
        FileUtil fileUtil = new FileUtil(path);

        String tempLetters;
        if(path.endsWith(".txt") || path.endsWith(".doc")||path.endsWith(".docx")){
            tempLetters = fileUtil.readFile(); //暂存文件字符内容
        }else {
            tempLetters = fileUtil.readFileS(path);
        }

        List<WordsInfo> winfo = new ArrayList<>();  //保存不重复的单词
        String delim = "'\", 0123456789-/?().:@#!$%^&*_+-\r\n"; //处理分割的字符

        StringTokenizer st=new StringTokenizer(tempLetters,delim);
        while(st.hasMoreTokens()) {
            String temp = st.nextToken().toLowerCase(); //处理为小写
            int flag = isContain(winfo,temp);
            if(flag==-1){
                winfo.add(new WordsInfo(temp,1));
            }else {
                WordsInfo wi = winfo.get(flag);
                wi.setNum(wi.getNum()+1);
                winfo.set(flag,wi);
            }
        }
        winfo.sort(Comparator.comparing(WordsInfo::getNum).reversed());
         return winfo;
    }
    //判断单词src是否在容器里
    public static int isContain(List<WordsInfo> list, String src){
        for (int i = 0; i < list.size(); i++){
            if (list.get(i).getWord().equals(src)){
                return i;
            }
        }
        return -1;
    }


    /**
     *  输出文件中所有不重复的单词，按照出现次数由多到少排列，出现次数同样多的，以字典序排列,排除掉stopwords.txt里面的词语
     *  不支持缩写 --> I'm
     *  返回该单词组
     * */
    public static List<WordsInfo> DistinctWordsExceptSome(String path) throws IOException{
        String except = new FileUtil().readLocal("stopwords.txt");
        List<String> listexcept= new ArrayList<>();
        StringTokenizer st=new StringTokenizer(except," ");
        while (st.hasMoreTokens()){
            listexcept.add(st.nextToken());
        }

        FileUtil fileUtil = new FileUtil(path);

        String tempLetters;
        if(path.endsWith(".txt") || path.endsWith(".doc")||path.endsWith(".docx")){
            tempLetters = fileUtil.readFile(); //暂存文件字符内容
        }else {
            tempLetters = fileUtil.readFileS(path);
        }

        List<WordsInfo> winfo = new ArrayList<>();  //保存不重复的单词

        tempLetters= tempLetters.replaceAll("[^a-zA-z]"," ");
        st=new StringTokenizer(tempLetters," ");
        while(st.hasMoreTokens()) {
            String temp = st.nextToken().toLowerCase(); //处理为小写
            int flag = isContain(winfo,temp);
            if(flag==-1){
                winfo.add(new WordsInfo(temp,1));
            }else {
                WordsInfo wi = winfo.get(flag);
                wi.setNum(wi.getNum()+1);
                winfo.set(flag,wi);
            }
        }
        winfo.sort(Comparator.comparing(WordsInfo::getNum).reversed());
        return winfo;
    }

    /**
     * 输出出现次数最多的前 n 个单词
     * */
    public static void showTopN(int n, String path)throws IOException{
        List<WordsInfo> list = DistinctWords(path);
        if(n <= 0 || n > list.size()){
            System.out.println("N越界或非法！");
        }
        for (int i = 0; i < n; i++){
            System.out.println(list.get(i));
        }
    }

    public static void operating() throws IOException {
        System.out.print("输入操作：");
        Scanner input=new Scanner(System.in);
        String choice = input.nextLine();
        String path;
        while (true){
            if(choice.equals("quit")){
                return;
            }else if(choice.equals("wf.exe -c")){
                System.out.println("请输入文件路径");
                path = input.nextLine();
                showRate(path);
            }else if(choice.equals("wf.exe -n")){
                System.out.println("请输入文件路径");
                path = input.nextLine();
                System.out.println("输入n(最多的前 n 个单词)");
                int n = input.nextInt();
                showTopN(n,path);
            }else if(choice.equals("wf.exe -f")){
                System.out.println("请输入文件路径");
                path = input.nextLine();
                List<WordsInfo> list = DistinctWords(path);
                showTopN(list.size(),path);
            }else if(choice.equals("wf.exe -d")){
                System.out.println("请输入文件路径");
                path = input.nextLine();
                List<WordsInfo> list = DistinctWords(path);
                showTopN(list.size(),path);
            }
            System.out.print("输入操作：");
            choice = input.nextLine();
        }
    }


    public static void main(String[] args) throws IOException {
        operating();
    }


}
